/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * main.cc
 * Copyright (C) Michael J. Beer 2010 <michael.josef.beer@googlemail.com>
 * 
 * uniview is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * uniview is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>
#include "Transformation.h"
#include "Matrix.h"
#include "Point.h"
#include "Projection.h"
#include <SDL/SDL.h>


using namespace std;
using namespace uniview;

const int LEN = 5;
double beholderPos[] = {20.0, 5.0, 15.0};
double beholderDir[] = {1.0, 1.0, 1.0};
double points[LEN][3] = {
    {1.0, 0.0, 0.0},
    {0.0, 1.0, 0.0},
    {0.0, 0.0, 1.0},
    {0.5, 0.5, 0.5},
    {-2.1, 1.2, 0.5}
};

void setPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
    {
        int bpp = surface->format->BytesPerPixel;
        /* Here p is the address to the pixel we want to set */
        Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

        switch(bpp) {
            case 1:
                *p = pixel;
                break;

            case 2:
                *(Uint16 *)p = pixel;
                break;

            case 3:
                if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
                    p[0] = (pixel >> 16) & 0xff;
                    p[1] = (pixel >> 8) & 0xff;
                    p[2] = pixel & 0xff;
                } else {
                    p[0] = pixel & 0xff;
                    p[1] = (pixel >> 8) & 0xff;
                    p[2] = (pixel >> 16) & 0xff;
                }
                break;

            case 4:
                *(Uint32 *)p = pixel;
                break;
        }
    }

SDL_Surface *screen;


int main()
{
    Transformation *trans = Transformation::getAlignToXAxis(beholderDir, beholderPos);
    cout << Matrix::toString(trans->getM(), trans->getN(), trans->getMatrix()) << endl;
    cout << Point::toString(trans->getM(), trans->getTranslation()) << endl;
    Projection projection;
    
    double **res = new double *[LEN];
    double **point2D = new double *[LEN];
    for(int i =0; i < LEN; i++) {
        cout << endl;
        cout << Point::toString(3, points[i]);
        res[i] = Point::newPoint(3);
        point2D[i] = new double[2];
        trans->apply(points[i], res[i]);
        cout << endl << "Transformiert: ";
        cout << Point::toString(3, res[i]);
        projection.fisheyeProjection(res[i], point2D[i]);
        cout << "Projiziert (Fischauge): " << std::endl;
        cout << point2D[i][0] << " " << point2D[i][1] << std::endl;
        cout << "Projiziert (Gerade):" << std::endl;
        projection.plainProjection(res[i], point2D[i]);
        cout << point2D[i][0] << " " << point2D[i][1] << std::endl;
    };
    cout << endl;
    char c;
    cin >> c;

    if(SDL_Init(SDL_INIT_VIDEO) != 0) {
        cerr << "Konnte SDL nicht initialisieren!" << std::endl;
        return -1;
    };
    atexit(SDL_Quit);
    
    screen = SDL_SetVideoMode(640, 480, 16, 0);
    Uint32 white = SDL_MapRGB(screen->format, 0, 0, 0);
    SDL_LockSurface(screen);
    for(int i = 1; i < LEN; i++) {
        setPixel(screen, point2D[i][0], point2D[i][1], white);
    };
    SDL_UnlockSurface(screen);
    SDL_UpdateRect(screen, 0, 0, 0, 0);
    SDL_Delay(50000);

    cin >> c;
    
    free(screen);
    for( int i = 0; i < LEN; i++)
    {
        delete point2D[i];
    }
    delete[] point2D;
    delete trans;
    return 0;
}
